package com.example.library.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.library.common.ResultCode;
import com.example.library.dto.BaseQueryRequest;
import com.example.library.entity.Category;
import com.example.library.mapper.CategoryMapper;
import com.example.library.service.CategoryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 图书分类服务实现类
 *
   */
@Slf4j
@Service
@RequiredArgsConstructor
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

    private final CategoryMapper categoryMapper;

    @Override
    public IPage<Category> getCategoryPage(BaseQueryRequest queryRequest) {
        Page<Category> page = new Page<>(queryRequest.getCurrent(), queryRequest.getSize());
        return categoryMapper.selectCategoryPage(page, queryRequest.getKeyword(), null, null);
    }

    @Override
    public List<Category> getCategoryTree() {
        List<Category> allCategories = getEnabledCategories();
        return buildCategoryTree(allCategories, Category.ROOT_PARENT_ID);
    }

    @Override
    public List<Category> getEnabledCategories() {
        return categoryMapper.selectEnabledCategories();
    }

    @Override
    public List<Category> getChildCategories(Long parentId) {
        return categoryMapper.selectByParentId(parentId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createCategory(Category category) {
        // 检查分类名称是否存在
        if (existsByName(category.getName(), category.getParentId())) {
            throw new RuntimeException("分类名称已存在");
        }

        // 设置默认值
        if (category.getParentId() == null) {
            category.setParentId(Category.ROOT_PARENT_ID);
        }
        if (category.getStatus() == null) {
            category.setStatus(Category.STATUS_ENABLED);
        }
        if (category.getSortOrder() == null) {
            category.setSortOrder(0);
        }

        return save(category);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCategory(Category category) {
        Category existingCategory = getById(category.getId());
        if (existingCategory == null) {
            throw new RuntimeException(ResultCode.CATEGORY_NOT_FOUND.getMessage());
        }

        // 检查分类名称是否被其他分类使用
        Category nameCheck = categoryMapper.selectByNameAndParentId(category.getName(), category.getParentId());
        if (nameCheck != null && !nameCheck.getId().equals(category.getId())) {
            throw new RuntimeException("分类名称已存在");
        }

        // 不能将分类设置为自己的子分类
        if (category.getParentId() != null && category.getParentId().equals(category.getId())) {
            throw new RuntimeException("不能将分类设置为自己的子分类");
        }

        category.setUpdatedTime(LocalDateTime.now());
        return updateById(category);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteCategory(Long categoryId) {
        Category category = getById(categoryId);
        if (category == null) {
            throw new RuntimeException(ResultCode.CATEGORY_NOT_FOUND.getMessage());
        }

        // 检查是否有子分类
        if (hasChildren(categoryId)) {
            throw new RuntimeException("该分类下存在子分类，无法删除");
        }

        // 检查是否有图书
        if (hasBooks(categoryId)) {
            throw new RuntimeException("该分类下存在图书，无法删除");
        }

        return removeById(categoryId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchDeleteCategories(List<Long> categoryIds) {
        for (Long categoryId : categoryIds) {
            // 检查是否有子分类
            if (hasChildren(categoryId)) {
                throw new RuntimeException("存在分类下有子分类，无法批量删除");
            }

            // 检查是否有图书
            if (hasBooks(categoryId)) {
                throw new RuntimeException("存在分类下有图书，无法批量删除");
            }
        }

        return removeByIds(categoryIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCategoryStatus(Long categoryId, Integer status) {
        Category category = getById(categoryId);
        if (category == null) {
            throw new RuntimeException(ResultCode.CATEGORY_NOT_FOUND.getMessage());
        }

        category.setStatus(status);
        return updateById(category);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateCategoryStatus(List<Long> categoryIds, Integer status) {
        return categoryMapper.batchUpdateStatus(categoryIds, status) > 0;
    }

    @Override
    public boolean existsByName(String name, Long parentId) {
        return categoryMapper.selectByNameAndParentId(name, parentId) != null;
    }

    @Override
    public boolean hasChildren(Long categoryId) {
        return categoryMapper.countChildren(categoryId) > 0;
    }

    @Override
    public boolean hasBooks(Long categoryId) {
        return categoryMapper.countBooks(categoryId) > 0;
    }

    @Override
    public Object getCategoryStatistics() {
        Map<String, Object> statistics = new HashMap<>();
        
        // 总分类数
        statistics.put("totalCategories", count());
        
        // 顶级分类数
        statistics.put("topLevelCategories", categoryMapper.countCategories(null, Category.ROOT_PARENT_ID));
        
        // 启用分类数
        statistics.put("enabledCategories", categoryMapper.countCategories(Category.STATUS_ENABLED, null));
        
        // 禁用分类数
        statistics.put("disabledCategories", categoryMapper.countCategories(Category.STATUS_DISABLED, null));
        
        // 热门分类
        statistics.put("popularCategories", categoryMapper.selectPopularCategories(5));
        
        return statistics;
    }

    /**
     * 构建分类树
     *
     * @param categories 所有分类
     * @param parentId 父分类ID
     * @return 分类树
     */
    private List<Category> buildCategoryTree(List<Category> categories, Long parentId) {
        List<Category> tree = new ArrayList<>();
        
        for (Category category : categories) {
            if (parentId.equals(category.getParentId())) {
                List<Category> children = buildCategoryTree(categories, category.getId());
                category.setChildren(children);
                tree.add(category);
            }
        }
        
        // 按排序字段排序
        return tree.stream()
                .sorted((c1, c2) -> {
                    int sort1 = c1.getSortOrder() != null ? c1.getSortOrder() : 0;
                    int sort2 = c2.getSortOrder() != null ? c2.getSortOrder() : 0;
                    return Integer.compare(sort1, sort2);
                })
                .collect(Collectors.toList());
    }

}